package com.example.aidlservicedemo;

import android.Manifest;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Log;

import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;

import java.util.ArrayList;
import java.util.List;

/**
 * AIDLService 是一个基于 Android Binder 的服务类，用于提供跨进程通信（AIDL）的功能。
 * 该服务实现了 ITest 接口定义的方法，并通过内部类 AIDLServiceImpl 来处理具体的业务逻辑。
 *
 * <p>主要功能包括：
 * <ul>
 *   <li>返回字符串列表</li>
 *   <li>返回 Person 对象列表</li>
 *   <li>拨打电话</li>
 *   <li>触发播放监听器的回调</li>
 * </ul>
 *
 * @author Jin
 * @since 2021/7/1
 */
public class AIDLService extends Service {

    /**
     * mBinder 是 AIDL 接口 ITest.Stub 的实例，用于绑定服务并提供远程调用接口。
     */
    public ITest.Stub mBinder = new AIDLServiceImpl();

    /**
     * 获取预定义的国家/地区名称列表。
     *
     * @return 包含国家/地区名称的字符串列表
     */
    public static List<String> getList() {
        List<String> country = new ArrayList<>();
        country.add("India");
        country.add("Bhutan");
        country.add("Nepal");
        country.add("USA");
        country.add("Canada");
        country.add("China");
        return country;
    }

    /**
     * onBind 方法在绑定服务时被调用，返回 IBinder 实例供客户端访问。
     *
     * @param intent 绑定请求的 Intent
     * @return 返回 mBinder 实例
     */
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    /**
     * 获取预定义的 Person 对象列表。
     *
     * @return 包含 Person 对象的列表
     */
    public List<Person> getPersons() {
        List<Person> person = new ArrayList<>();
        person.add(new Person("A", 10));
        person.add(new Person("B", 20));
        person.add(new Person("C", 30));
        person.add(new Person("D", 40));
        person.add(new Person("E", 50));
        person.add(new Person("F", 60));
        return person;
    }

    /**
     * AIDLServiceImpl 是 ITest.Stub 的实现类，负责具体方法的执行。
     * 所有远程调用的方法都在此类中实现。
     */
    private class AIDLServiceImpl extends ITest.Stub {

        /**
         * onTransact 方法用于处理 Binder 事务。
         * 此处添加了自定义权限校验逻辑，确保只有具有特定权限的调用者才能访问服务。
         *
         * @param code 事务码
         * @param data 输入数据包
         * @param reply 输出回复包
         * @param flags 事务标志
         * @return 是否成功处理事务
         * @throws RemoteException 如果发生远程异常
         */
        @Override
        public boolean onTransact(int code, Parcel data, Parcel reply,
            int flags) throws RemoteException {
            Log.i("TAG", "onTransact is running on main thread: " + ThreadUtils.isMainThread());
            // 检查调用方是否拥有自定义权限
            if (checkCallingOrSelfPermission("com.example.aidlservicedemo.CUSTOM_PERMISSION") !=
                PackageManager.PERMISSION_GRANTED) {
                // 如果没有权限，拒绝调用
                return false;
            }
            // 继续正常的 Binder 事务处理
            return super.onTransact(code, data, reply, flags);
        }

        /**
         * 将两个整数相加并返回结果。
         *
         * @param num1 第一个整数
         * @param num2 第二个整数
         * @return 两数之和
         */
        @Override
        public int addNumbers(int num1, int num2) {
            Log.i("TAG", "addNumbers is running on main thread: " + ThreadUtils.isMainThread());
            Log.i("TAG", "addNumbers() called with: num1 = [" + num1 + "], num2 = [" + num2 + "]");
            // 远程调用，模拟耗时操作，产生anr
            Log.i("TAG", "run: 执行耗时操作");
            SystemClock.sleep(5000);
            return num1 + num2;
        }

        /**
         * 获取字符串列表。
         *
         * @return 字符串列表
         */
        @Override
        public List<String> getStringList() {
            Log.i("TAG", "getStringList is running on main thread: " + ThreadUtils.isMainThread());
            return getList();
        }

        /**
         * 获取 Person 对象列表。
         *
         * @return Person 对象列表
         */
        @Override
        public List<Person> getPersonList() {
            Log.i("TAG", "getPersonList is running on main thread: " + ThreadUtils.isMainThread());
            return getPersons();
        }

        /**
         * 根据提供的电话号码发起通话。
         * 如果没有 CALL_PHONE 权限，则通过通知提醒用户授权。
         *
         * @param number 要拨打的电话号码
         */
        @Override
        public void placeCall(String number) {
            Log.i("TAG", "placeCall is running on main thread: " + ThreadUtils.isMainThread());
            // 检查是否授予 CALL_PHONE 权限
            if (ActivityCompat.checkSelfPermission(getApplicationContext(),
                Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
                // 创建跳转到 MainActivity 的 PendingIntent
                Intent intent = new Intent(getApplicationContext(), MainActivity.class);
                PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(),
                    (int) System.currentTimeMillis(), intent, 0);
                // 构建通知
                Notification n = new Notification.Builder(getApplicationContext()).setContentTitle(
                        "AIDL Server App").setContentText("Please grant call permission from settings")
                    .setSmallIcon(R.drawable.ic_launcher).setContentIntent(pendingIntent)
                    .setAutoCancel(true).build();
                // 发送通知
                NotificationManager notificationManager =
                    (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
                notificationManager.notify(0, n);
                return;
            }
            // 启动拨号界面
            Intent intent = new Intent(Intent.ACTION_CALL);
            intent.setData(Uri.parse("tel:" + number));
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.addFlags(Intent.FLAG_FROM_BACKGROUND);
            startActivity(intent);
        }

        /**
         * 触发播放监听器的 onSuccess 回调。
         *
         * @param iPlayListener 播放监听器接口
         * @throws RemoteException 如果发生远程异常
         */
        @Override
        public void involved(IPlayListener iPlayListener) throws RemoteException {
            Log.i("TAG", "involved is running on main thread: " + ThreadUtils.isMainThread());
            // 检查监听器是否为空
            if (iPlayListener != null) {
                // 创建 Bundle 并填充数据
                Bundle bundle = new Bundle();
                bundle.putString("user", "周杰伦");
                bundle.putInt("age", 55);
                // 调用监听器的 onSuccess 方法
                iPlayListener.onSuccess("你好", bundle);
            }
        }

    }

}
